package Net

import (
	"fmt"
	"github.com/sentiger/ftcp/Iface"
	"github.com/sentiger/ftcp/Utils"
	_ "github.com/sentiger/ftcp/Utils"
	"net"
	"time"
)

type Server struct {
	Name       string
	IPVersion  string
	IP         string
	Port       int
	msgHandler Iface.IMsgHandler
	connMgr    Iface.IConnManager
	// 设置conn回调方法
	OnConnStart func(conn Iface.IConnection)
	OnConnStop  func(conn Iface.IConnection)
}

func (s *Server) Start() {
	fmt.Printf("[START] Server name: %s,listenner at IP: %s, Port %d is starting\n", s.Name, s.IP, s.Port)
	go func() {
		// 开启进程池
		s.msgHandler.StartWorkerPool()
		//1 获取一个TCP的Addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Println("resolve tcp addr err: ", err)
			return
		}
		//2 监听服务器地址
		listenner, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen", s.IPVersion, "err", err)
			return
		}
		//已经监听成功
		fmt.Println("start ftcp server  ", s.Name, " success, now lister...")
		var cid uint32
		cid = 0
		//3 启动server网络连接业务
		for {
			//3.1 阻塞等待客户端建立连接请求
			conn, err := listenner.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err ", err)
				continue
			}
			//3.2 设置服务器最大连接控制,如果超过最大连接，那么则关闭此新的连接
			if s.connMgr.Len() >= Utils.GlobalObject.MaxConn {
				conn.Close()
				continue
			}
			//3.3 处理该新连接请求的 业务 方法， 此时应该有 handler 和 conn是绑定的
			dealConn := NewConnection(s, conn, cid, s.msgHandler)
			cid++
			//3.4 启动当前链接的处理业务
			go dealConn.Start()
		}
	}()

}

func (s *Server) Stop() {
	s.connMgr.ClearConn()
}

func (s *Server) Serve() {
	s.Start()
	for {
		time.Sleep(10 * time.Second)
	}
}

func (s *Server) AddRouter(msgId uint32, router Iface.IRouter) {
	s.msgHandler.AddRouter(msgId, router)
}

// 获取管理器
func (s *Server) GetConnMgr() Iface.IConnManager {
	return s.connMgr
}

// 回调函数
func (s *Server) SetOnConnStart(hookFunc func(conn Iface.IConnection)) {
	s.OnConnStart = hookFunc
}
func (s *Server) SetOnConnStop(hookFunc func(conn Iface.IConnection)) {
	s.OnConnStop = hookFunc
}
func (s *Server) CallOnConnStart(conn Iface.IConnection) {
	if s.OnConnStart != nil {
		s.OnConnStart(conn)
	}
}
func (s *Server) CallOnConnStop(conn Iface.IConnection) {
	if s.OnConnStop != nil {
		s.OnConnStop(conn)
	}
}

// 回调end

func NewServer(name string) Iface.IServer {
	s := &Server{
		Name:       Utils.GlobalObject.Name,
		IPVersion:  "tcp4",
		IP:         Utils.GlobalObject.Host,
		Port:       Utils.GlobalObject.TcpPort,
		msgHandler: NewMsgHandler(), //msgHandler 初始化
		connMgr:    NewConnManager(),
	}
	return s
}
